package com.superyee.commonlib.http;

import android.content.Context;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.superyee.commonlib.constants.AppConfig;
import com.superyee.commonlib.logic.BaseLogic;
import com.superyee.commonlib.utils.AndroidUtil;
import com.superyee.commonlib.utils.gson.GsonHelper;
import com.tencent.bugly.crashreport.CrashReport;

import org.apache.http.conn.ConnectTimeoutException;

import java.io.File;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import okhttp3.Call;
import okhttp3.Response;


public class HttpHelper {
    /**
     * 上下文环境
     */
    private Context mContext;

    /**
     * 单例-实例化对象
     */
    private static volatile HttpHelper instance;


    /**
     * 构造函数--初始化
     *
     * @param context
     */
    private HttpHelper(Context context) {
        super();
        mContext = context.getApplicationContext();
    }

    public static HttpHelper getInstance(Context context) {
        if (instance == null) {
            synchronized (HttpHelper.class) {
                if (instance == null) {
                    instance = new HttpHelper(context.getApplicationContext());
                }
            }
        }
        return instance;
    }

    private void parseResponse(int action, int statusCode, String response, HttpResponseListener listener, Object obj) {
        if (statusCode < 300) {
            //操作成功
            if (listener.mType == String.class) {
                listener.onSuccess(statusCode, action, response, obj);
            } else {
                Object o = GsonHelper.fromJson(response, listener.mType);
                listener.onSuccess(statusCode, action, o, obj);
            }
            listener.onFinish(action);
        } else {
            if (statusCode == 404) {
                listener.onFailure(statusCode, action, "请求地址不存在", null);
            } else if (statusCode == 401) { //token失效
                listener.onFailure(statusCode, action, response, null);
            } else {
                JSONObject jsonObject = null;
                try {
                    jsonObject = JSON.parseObject(response);
                } catch (Exception e) {
                    CrashReport.postCatchedException(new Throwable(e.getMessage() + "   result: ==== " + response));
                }
                if (jsonObject == null) {
                    listener.onFailure(statusCode, action, AppConfig.UNKNOWNEXCEPTION, null);
                } else {
                    //新接口直接toast异常信息
                    String error = BaseLogic.getError(response);
                    listener.onFailure(statusCode, action, error, null);
                    CrashReport.postCatchedException(new Throwable(response));
                }
            }
            listener.onFinish(action);
        }

    }


    public void delete(final int action, final String url, HttpParams params, final HttpResponseListener listener, final Object obj) {
        listener.onStart(action, url);
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);

        OkHttpClientManager.delete(mContext, url, params != null ? params.getParams() : null, new OkHttpClientManager.ResultCallback() {

            @Override
            public void onError(Call request, Exception e) {
                listener.onFailure(-1, action, parseError(e), e);
                listener.onFinish(action);
            }

            @Override
            public void onResponse(int code, String response) {
                parseResponse(action, code, response, listener, obj);
            }
        });
    }

    public void doGet(final int action, final String url, final HttpResponseListener listener, final Object obj) {
        listener.onStart(action, url);
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);

        OkHttpClientManager.getAsyn(mContext, url, new OkHttpClientManager.ResultCallback() {
            @Override
            public void onError(Call request, Exception e) {
                listener.onFailure(-1, action, parseError(e), e);
                listener.onFinish(action);
            }

            @Override
            public void onResponse(int code, String response) {
                parseResponse(action, code, response, listener, obj);
            }
        });
    }

    public void deleteJson(final int action, final String url, final String jsonStr,
                           final HttpResponseListener listener, final Object obj) {
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);
        OkHttpClientManager.deleteJson(mContext, url, jsonStr, new OkHttpClientManager.ResultCallback() {
            @Override
            public void onError(Call request, Exception e) {
                listener.onFailure(-1, action, parseError(e), e);
                listener.onFinish(action);
                CrashReport.postCatchedException(e);
            }

            @Override
            public void onResponse(int code, String response) {
                parseResponse(action, code, response, listener, obj);
            }
        });
    }

    public void putJson(final int action, final String url, final String jsonStr,
                        final HttpResponseListener listener, final Object obj) {
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);
        OkHttpClientManager.putJson(mContext, url, jsonStr, new OkHttpClientManager.ResultCallback() {
            @Override
            public void onError(Call request, Exception e) {
                listener.onFailure(-1, action, parseError(e), e);
                listener.onFinish(action);
                CrashReport.postCatchedException(e);
            }

            @Override
            public void onResponse(int statusCode, String response) {
                parseResponse(action, statusCode, response, listener, obj);
            }
        });
    }



    public void doPostJson(final int action, final String url, final String jsonStr,
                           final HttpResponseListener listener, final Object obj) {
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);
        OkHttpClientManager.postJsonAsyn(mContext, url, jsonStr, new OkHttpClientManager.ResultCallback() {
            @Override
            public void onError(Call request, Exception e) {
                listener.onFailure(-1, action, parseError(e), e);
                listener.onFinish(action);
                CrashReport.postCatchedException(e);
            }

            @Override
            public void onResponse(int statusCode, String response) {
                parseResponse(action, statusCode, response, listener, obj);
            }
        });
    }

    /**
     * 同步post请求
     *
     * @param url
     * @param params
     * @return
     */
    public HttpResponse postSync(String url, HttpParams params) {
        try {
            return OkHttpClientManager.postSyn(mContext, url, params.getFiles(), params.getFileKey(), params.getParams());
        } catch (IOException e) {
            e.printStackTrace();
            return new HttpResponse(-1, e.getMessage());
        }
    }

    public String post(String url, HttpParams params) {
        try {
            Response response = OkHttpClientManager.post(mContext, url, params.getParams());
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 同步get请求
     *
     * @param url
     * @return
     */
    public HttpResponse getSync(String url) {
        try {
            return OkHttpClientManager.getSyn(mContext, url);
        } catch (IOException e) {
            e.printStackTrace();
            return new HttpResponse(-1, e.getMessage());
        }
    }


    private String parseError(Exception e) {
        if (e != null && (e instanceof SocketTimeoutException || SocketTimeoutException.class.equals(e.getCause()) || e instanceof ConnectTimeoutException) || e instanceof UnknownHostException
                || e instanceof ConnectException) {
            return AppConfig.CONNECTTIMEOUT;
        }
        return AppConfig.UNKNOWNEXCEPTION + e == null ? "" : e.getMessage();
    }

    public void doPatch(final int action, final String url, HttpParams params,
                        final HttpResponseListener listener, final Object obj) {
        doPatch(action, url, params, listener, obj, null);
    }

    public void doPatch(final int action, final String url, HttpParams params,
                        final HttpResponseListener listener, final Object obj, String contentType) {
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);
        try {
            OkHttpClientManager.patchAsyn(mContext, url, new OkHttpClientManager.ResultCallback() {
                @Override
                public void onError(Call request, Exception e) {
                    listener.onFailure(-1, action, parseError(e), e);
                    listener.onFinish(action);
                    CrashReport.postCatchedException(e);
                }

                @Override
                public void onResponse(int statusCode, String response) {
                    parseResponse(action, statusCode, response, listener, obj);
                }
            }, params.getFiles(), params.getFileKey(), params.getParams(), contentType);
        } catch (IOException e) {
            e.printStackTrace();
            listener.onFailure(-1, action, "error :" + e.getMessage(), e);
            listener.onFinish(action);
        }
    }




    public void doPost(final int action, final String url, HttpParams params,
                       final HttpResponseListener listener, final Object obj) {
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);
        try {
            OkHttpClientManager.postAsyn(mContext, url, new OkHttpClientManager.ResultCallback() {
                @Override
                public void onError(Call request, Exception e) {
                    listener.onFailure(-1, action, parseError(e), e);
                    listener.onFinish(action);
                    CrashReport.postCatchedException(e);
                }

                @Override
                public void onResponse(int statusCode, String response) {
                    parseResponse(action, statusCode, response, listener, obj);
                }
            }, params.getFiles(), params.getFileKey(), params.getParams(), null);
        } catch (IOException e) {
            e.printStackTrace();
            listener.onFailure(-1, action, "error :" + e.getMessage(), e);
            listener.onFinish(action);
        }
    }


    public void doPut(int action, String url, HttpParams params, HttpResponseListener listener, Object obj) {
        doPut(action, url, params, listener, obj, null);
    }


    public void doPut(final int action, final String url, HttpParams params,
                      final HttpResponseListener listener, final Object obj, String contentType) {
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);
        try {
            OkHttpClientManager.putAsyn(mContext, url, new OkHttpClientManager.ResultCallback() {
                @Override
                public void onError(Call request, Exception e) {
                    listener.onFailure(-1, action, parseError(e), e);
                    listener.onFinish(action);
                    CrashReport.postCatchedException(e);
                }

                @Override
                public void onResponse(int statusCode, String response) {
                    parseResponse(action, statusCode, response, listener, obj);
                }
            }, params.getFiles(), params.getFileKey(), params.getParams(), contentType);
        } catch (IOException e) {
            e.printStackTrace();
            listener.onFailure(-1, action, "error :" + e.getMessage(), e);
            listener.onFinish(action);
        }
    }

    /**
     * @param action
     * @param url      下载地址
     * @param destDir  保存目录
     * @param fileName 保存文件名
     * @param listener
     * @param object
     */
    public void download(final int action, String url, String destDir, String fileName, final HttpFileResponseListener listener, final Object object) {
        if (!AndroidUtil.isNetworkConnection(mContext)) {
            listener.noNetwork(action);
            listener.onFinish(action);
            return;
        }
        listener.onStart(action, url);
        OkHttpClientManager.downloadAsyn(mContext, url, destDir, fileName, new OkHttpClientManager.FileCallback() {
            @Override
            public void onSuccess(File file) {
                if (listener != null) {
                    listener.onSuccess(action, file, object);
                    listener.onFinish(action);
                }
            }

            @Override
            public void onDownloading(long progress, long total) {
                if (listener != null) {
                    listener.onProgress(action, progress, total);
                }
            }

            @Override
            public void onDownloadFailed(String message) {
                if (listener != null) {
                    listener.onFailure(action, BaseLogic.getError(message), null);
                    listener.onFinish(action);
                }
            }
        });
    }

}
